#include <QList>
#include <QNetworkInterface>
#include <QNetworkAddressEntry>
#include <QDebug>
#include <QMessageBox>
#include <QKeyEvent>
#include <QEvent>
#include <QFileDialog>
#include <QMapIterator>
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "Common.h"


MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    setWindowTitle(tr("ComAssist"));

    linkState = false;
    circleState = false;

    recvAscii = true;
    sendAscii = true;
    recvNewline = false;
    recvPause = false;

    ui->lineEditSendPeriod->setText("1000");
    on_comboBoxComType_currentIndexChanged(0);

//    ui->comboBox_Dest->setEditable(true);

    statusWidget = new StatusWidget(this);
    ui->statusBar->addWidget(statusWidget,1);

    uCom = new UCommunication();
    timer = NULL;

    ui->textEditSend->installEventFilter(this);
}

MainWindow::~MainWindow()
{
    if (statusWidget)
    {
        delete statusWidget;
        statusWidget = NULL;
    }
    if (uCom)
    {
        delete uCom;
        uCom = NULL;
    }
    delete ui;
}

void MainWindow::changeEvent(QEvent *e)
{
    QMainWindow::changeEvent(e);
    switch (e->type()) {
    case QEvent::LanguageChange:
        ui->retranslateUi(this);
        break;
    default:
        break;
    }
}
bool MainWindow::eventFilter(QObject *target, QEvent *event)
{
    if (target == ui->textEditSend)
    {
        if (event->type() == QEvent::KeyPress)
        {
            QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
            if (!sendAscii) //十六进制输入
            {
                if (
                     (keyEvent->key() >= Qt::Key_A && keyEvent->key() <= Qt::Key_F)
                    ||(keyEvent->key() >= Qt::Key_0 && keyEvent->key() <= Qt::Key_9)
                    || keyEvent->key() == Qt::Key_Backspace
                    || keyEvent->key() == Qt::Key_Delete
                    || keyEvent->key() == Qt::Key_Return
                    || keyEvent->key() == Qt::Key_Enter
                    || keyEvent->key() == Qt::Key_Left
                    || keyEvent->key() == Qt::Key_Right
                    || keyEvent->key() == Qt::Key_Down
                    || keyEvent->key() == Qt::Key_Up
                    || keyEvent->key() == Qt::Key_Space
                    )
                {
                    return QMainWindow::eventFilter(target,event);
                }
                else
                {
                    return true;
                }
            }
            else    //十进制输入
            {
                return QMainWindow::eventFilter(target,event);
            }
        }
    }
    return QMainWindow::eventFilter(target,event);
}

//显示接收的数据
void MainWindow::DisplayText(const char *data, quint64 maxSize)
{
    QString dataDis;
    int i = 0;

    //数据错误
    if (data == NULL || maxSize <= 0)
        return;

    statusWidget->slotAddCount(maxSize, ADDRECVCOUNT);

    if (recvPause)                       //暂停显示
        return;

    QByteArray recvData(data, maxSize);
    if (!recvAscii)                     //接收区十六进制显示
    {
        //data ---> hex data
        dataDis = recvData.toHex().data();
        for (i=maxSize; i>=1; i--)
        {
            dataDis.insert(i*2, " ");
        }
    }
    else                                //接收区十进制显示
    {
        dataDis = QString(recvData);
    }

    if (recvNewline)                     //接收区换行显示
    {
        ui->textEditRecv->append(dataDis);
    }
    else
    {
        ui->textEditRecv->moveCursor(QTextCursor::End);
        ui->textEditRecv->insertPlainText(dataDis);
    }
    ui->textEditRecv->ensureCursorVisible();
}

int MainWindow::getUdpDestIPPort(QString &ip, quint16 &port)
{
    QString dest = ui->comboBox_Dest->currentText();
    QStringList values = dest.split(':');
    if (values.length() < 2)
        return -1;
    ip = values.at(0);
    port = values.at(1).toUShort();
    return 0;
}

void MainWindow::OpenUDP()
{
    if (linkState)         //关闭 UDP通信
    {
        ChangeLinkState(false);
        ui->lineEdit_udpIP->setDisabled(false);
        ui->lineEdit_udpPort->setDisabled(false);
        qDebug()<<"Close UDP link";
    }
    else        //打开 UDP通信
    {
        UdpSetStruct udpInfo;
        udpInfo.localIP = ui->lineEdit_udpIP->text();
        udpInfo.localPort = ui->lineEdit_udpPort->text().toUShort();
        qDebug()<<"Open UDP link:"<<udpInfo.localIP<<" Port:"<<udpInfo.localPort;

        uCom->SetComParam(UDPType, udpInfo);
        if (!uCom->OpenCom())
        {   //打开失败
            statusWidget->slotMessage(tr(StatusMesg[EOPEN]));
            uCom->CloseCom();
        }
        else
        {   //打开成功
            ChangeLinkState(true);
            ui->lineEdit_udpIP->setDisabled(true);
            ui->lineEdit_udpPort->setDisabled(true);
            connect(uCom,SIGNAL(sigComData(const char*,quint64)),
                    this,SLOT(slotDataCom(const char*,quint64)));
        }

    }
}

void MainWindow::OpenTCPServer()
{
    if (linkState)         //关闭
    {
        ChangeLinkState(false);
        ui->lineEdit_tcpsIP->setDisabled(false);
        ui->lineEdit_tcpsPORT->setDisabled(false);
        qDebug()<<"Close TCP SERVER link";
    }
    else
    {
        TCPSSetStruct tcpSet;
        tcpSet.localIP = ui->lineEdit_tcpsIP->text();
        tcpSet.localPort = ui->lineEdit_tcpsPORT->text().toUShort();

        qDebug()<<"Open TCP server:"<<tcpSet.localIP<<" Port:"<<tcpSet.localPort;
        uCom->SetComParam(TCPSType, tcpSet);
        if (!uCom->OpenCom())
        {   //打开失败
            statusWidget->slotMessage(tr(StatusMesg[EOPEN]));
            uCom->CloseCom();
        }
        else
        {   //打开成功
            ChangeLinkState(true);
            ui->lineEdit_tcpsIP->setDisabled(true);
            ui->lineEdit_tcpsPORT->setDisabled(true);

            connect(uCom,SIGNAL(sigComData(const char*,quint64)),
                    this,SLOT(slotDataCom(const char*,quint64)));
            connect(uCom, SIGNAL(sigComingConn(QString,quint16)),
                    this, SLOT(slotComingConnection(QString,quint16)));
            connect(uCom, SIGNAL(sigDeleteConn(QString,quint16)),
                    this, SLOT(slotDeleteConnection(QString,quint16)));
        }
    }
}

void MainWindow::OpenTCPClient()
{
    //    TCPCSetStruct tcpSet;
    //    if (LINKSTATUS)         //关闭
    //    {
    //        if (SENDING)
    //            return;
    //        LINKSTATUS = false;
    //        if (uCom->IsConnected())
    //        {
    //            uCom->CloseCom();
    //        }
    //    }
    //    else
    //    {
    //        uCom->SetComParam(TCPCType, tcpSet);
    //        disconnect(uCom, 0, 0, 0);
    //        connect(uCom, SIGNAL(sigTcpClientConn(QString,quint16)),
    //                this, SLOT(slotTcpClientConn(QString,quint16)));
    //        connect(uCom, SIGNAL(sigTcpClientError(QString)),
    //                this, SLOT(slotTcpClientError(QString)));
    //        uCom->OpenCom();
    //    }
}

void MainWindow::ChangeLinkState(bool linked)
{
    linkState = linked;
    if (linkState) {
        ui->comboBoxComType->setDisabled(true);
        ui->pushButton_open->setText("关闭");
        ui->label_state->setStyleSheet(QStringLiteral("image: url(:/image/led_on.png);"));
        statusWidget->slotMessage(tr(StatusMesg[SOPEN]));
    } else {
        ui->comboBoxComType->setDisabled(false);
        ui->pushButton_open->setText("打开");
        ui->label_state->setStyleSheet(QStringLiteral("image: url(:/image/led_off.png);"));
        if (uCom->IsConnected())
        {
            uCom->CloseCom();
            disconnect(uCom, 0, 0, 0);
        }
        statusWidget->slotMessage(tr(StatusMesg[UNLINK]));
    }
}
void  MainWindow::slotDataCom(const char *data, quint64 maxSize)
{
    DisplayText(data, maxSize);
}

void MainWindow::slotDataCom(QByteArray data, int size)
{
    DisplayText(data.data(), size);
}

void MainWindow::slotComingConnection(QString ip, quint16 port)
{
    if (ip.isEmpty())
        return;

    QString iptext = QString("%1:%2").arg(ip).arg(port);
    qDebug()<<"tcpclient connect:"<<iptext;

    int pos = ui->comboBox_Dest->count();
    ui->comboBox_Dest->insertItem(pos, iptext);
    setTcpClientCount();
}

void MainWindow::slotDeleteConnection(QString ip, quint16 port)
{
    if (ip.isEmpty())
        return;

    QString iptext = QString("%1:%2").arg(ip).arg(port);
    qDebug()<<"tcpclient delete :"<<iptext;

    int pos = ui->comboBox_Dest->findText(iptext);
    ui->comboBox_Dest->removeItem(pos);
    setTcpClientCount();
}

void MainWindow::setSendOptionDisabled(bool flag)
{
    ui->lineEditSendPeriod->setDisabled(flag);
    ui->textEditSend->setDisabled(flag);
    ui->checkBoxSendCircle->setDisabled(flag);
    ui->radioButtonSendAscii->setDisabled(flag);
    ui->radioButtonSendHex->setDisabled(flag);
    ui->pushLoadData->setDisabled(flag);
    ui->pushSendClear->setDisabled(flag);
    ui->comboBox_Dest->setDisabled(flag);
    ui->pushCloseRemote->setDisabled((flag));
}

void MainWindow::setTcpClientCount()
{
    int count = ui->comboBox_Dest->count() - 1;
    QString text = QString("All client connects (%1)").arg(count);
    ui->comboBox_Dest->setItemText(0, text);
}

void MainWindow::startCircleSend()
{
    timer = new QTimer();
    connect(timer,SIGNAL(timeout()), this, SLOT(SendText()));
    timer->start(sendPeriod);
    setSendOptionDisabled(true);
    ui->pushSend->setText(tr("STOP"));
    circleState = true;
}

void MainWindow::stopCircleSend()
{
    if (timer != NULL)
    {
        timer->stop();
        delete timer;
        timer = NULL;
    }
    setSendOptionDisabled(false);
    ui->pushSend->setText(tr("SEND"));
    circleState = false;
}

//void MainWindow::slotTcpClientConn(QString ip, quint16 port)
//{
//    LINKSTATUS = true;
//    statusWidget->slotMessage(tr(StatusMesg[SOPEN]));
//    disconnect(uCom,SIGNAL(sigComData(const char*,quint64)),0,0);
//    connect(uCom,SIGNAL(sigComData(const char*,quint64)),
//            this,SLOT(slotDataCom(const char*,quint64)));
//    connect(uCom, SIGNAL(sigTcpClientDisCon()),
//            this, SLOT(slotTcpClientDiscon()));
//}

//void MainWindow::slotTcpClientDiscon()
//{
//    LINKSTATUS = false;
//    if (uCom->IsConnected())
//    {
//        uCom->CloseCom();
//    }
//}

//void MainWindow::slotTcpClientError(QString error)
//{
//    qDebug()<<"MAINWINDOW:";
//    qDebug()<<error;
//    statusWidget->slotMessage(error);
//}

int MainWindow::SendText()
{
    int result = 0;

    QString ip;
    quint16 port;
    int ret = 0;

    int pos = -1;
    QString iptext;
    char *p = NULL;
    int temp = 0;

    if (textSDec.isEmpty() || textSDec.length() < 0)
        return 0;

    if (uCom->IsConnected())
    {
        switch(uCom->GetComType())
        {
        case UDPType:
            ret = getUdpDestIPPort(ip, port);
            if (ret == 0)
                result = uCom->SendData(textSDec.data(),textSDec.length(), ip, port);
            break;
        case TCPSType:
            if (ui->comboBox_Dest->count() == 1)
            {
                QMessageBox::warning(this, tr("WARNING"),
                                               tr("没有连接对象.\n"),
                                               QMessageBox::Ok,
                                               QMessageBox::Ok);
                result = 0;
                break;
            }
            if (ui->comboBox_Dest->currentIndex() == 0)
            {
                pos = ui->comboBox_Dest->count();
                while (pos-- > 1)
                {
                      iptext = ui->comboBox_Dest->itemText(pos);
                      QStringList list1 = iptext.split(':');
                      ip = list1.at(0);
                      port = list1.at(1).toInt();

                      qDebug()<<"IP:"<<ip<<"PORT:"<<port<<"data:"<<textSDec.data();
                      result = uCom->SendData(textSDec.data(),textSDec.length(), ip, port);
                }
            }
            else
            {
                iptext = ui->comboBox_Dest->currentText();
                QStringList list1 = iptext.split(':');
                ip = list1.at(0);
                port = list1.at(1).toInt();

                qDebug()<<"IP:"<<ip<<"PORT:"<<port<<"data:"<<textSDec.data();
                result = uCom->SendData(textSDec.data(),textSDec.length(), ip, port);
            }
            break;
        case TCPCType:
//            result = uCom->SendData(strSend.toAscii());
            break;
        default:
            result = -1;
            break;
        }
    }
    //qDebug()<<"send result:"<<result;
    if (result < 0)
        statusWidget->slotMessage(tr(StatusMesg[ESENDDATA]));
    else
        statusWidget->slotAddCount(textSDec.length(),ADDSENDCOUNT);
    return result;
}

/////////////////////////////////////////////////////////////////////////////////////////
void MainWindow::on_comboBoxComType_currentIndexChanged(int index)
{
    ui->stackedWidget->setCurrentIndex(index);
    ui->comboBox_Dest->clear();
    bool hide = true;
    switch (index) {
    case 0:
        comType = UDPType;
        ui->comboBox_Dest->addItem("127.0.0.1:8080");
        hide = false;
        break;
    case 1:
        comType = TCPSType;
        ui->comboBox_Dest->addItem("All client connects (0)");
        hide = false;
        break;
    case 2:
        comType = TCPCType;
        hide = true;
        break;
    case 3:
        comType = SERIALType;
        hide = true;
        break;
    default:
        break;
    }
    ui->label_Dest->setHidden(hide);
    ui->comboBox_Dest->setHidden(hide);
    ui->pushCloseRemote->setHidden(hide);
}

void MainWindow::on_pushButton_open_clicked()
{
    switch (comType) {
    case UDPType:
        OpenUDP();
        break;
    case TCPSType:
        OpenTCPServer();
        break;
    case TCPCType:
        OpenTCPClient();
        break;
    default:
        break;
    }
}

void MainWindow::on_pushSaveData_clicked()
{
    QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"),
                            "./DataRecved.txt", tr("Plain text doctument (*.txt)"));
    QFile file(fileName);
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
        return;

    QTextStream in(&file);
    in<<ui->textEditRecv->toPlainText();

    file.close();
}

void MainWindow::on_pushRecvClear_clicked()
{
    ui->textEditRecv->clear();
}

void MainWindow::on_pushLoadData_clicked()
{
    QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"),
                            ".", tr("Plain text doctument (*.txt)"));

    QFile file(fileName);
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
        return;

    QTextStream out(&file);
    ui->textEditSend->setText(out.readAll());

    file.close();
}

void MainWindow::on_pushSendClear_clicked()
{
    ui->textEditSend->clear();
}

void MainWindow::on_pushSend_clicked()
{
    if (linkState == false)
    {
        QMessageBox::warning(this, tr("WARNING"),
                           tr("Not connected.\n"),
                           QMessageBox::Ok, QMessageBox::Ok);
        return ;
    }
    QString textS = ui->textEditSend->toPlainText();
    if (textS.length() == 0)
        return;

    if (circleState)
    {
        stopCircleSend();
        return;
    }

    if (ui->checkBoxSendCircle->checkState()) //循环发送
    {
        sendPeriod = ui->lineEditSendPeriod->text().toInt(0,10);
        if (sendPeriod <= 0)  //得到时间数据错误
        {
            ui->lineEditSendPeriod->clear();
            QMessageBox::warning(this, tr("WARNING"),
                                           tr("请输入正确的时间间隔.\n"),
                                           QMessageBox::Ok,
                                           QMessageBox::Ok);
            return;
        }
    }

    if (!sendAscii)     //转成十进制
    {
        int length = textS.length();
        char *toText = new char[length];
        memset(toText,'\0',length);
        length = HexToDecDis(textS.toStdString().c_str(), toText, length);
        textSDec = QByteArray(toText, length);
        if (toText != NULL)
        {
            delete toText;
            toText = NULL;
        }
    }
    else
    {
        textSDec = QByteArray(textS.toStdString().c_str(), textS.size());
    }
    qDebug()<<"Send Text:"<<textSDec.toHex();

    if (ui->checkBoxSendCircle->checkState()) //循环发送
    {
        startCircleSend();
    }
    else
    {
        //调用发送函数
        SendText();
    }
    qDebug()<<"Send Over";
}

void MainWindow::on_pushCloseRemote_clicked()
{
    ui->comboBox_Dest->clearEditText();
}

void MainWindow::on_checkBoxRecvNewL_clicked(bool checked)
{
    recvNewline = checked;
}

void MainWindow::on_checkBoxRecvPause_clicked(bool checked)
{
    recvPause = checked;
}

void MainWindow::on_radioButtonRecvHex_clicked(bool checked)
{
    if (checked)
        recvAscii = false;
}

void MainWindow::on_radioButtonRecvAscii_clicked(bool checked)
{
    if (checked)
        recvAscii = true;
}

void MainWindow::on_radioButtonSendAscii_clicked(bool checked)
{
    if (!sendAscii)
        sendAscii = true;
    else
        return;

    QString text = ui->textEditSend->toPlainText();
    if (text.isEmpty())
        return;

    int length = text.length();
    char *toText = new char[length];
    memset(toText,'\0',length);
    HexToDecDis(text.toStdString().c_str(), toText, length);

    ui->textEditSend->clear();
    ui->textEditSend->append(QString(toText));
    if (toText != NULL)
    {
        delete toText;
        toText = NULL;
    }
}

void MainWindow::on_radioButtonSendHex_clicked(bool checked)
{
    if (sendAscii)
        sendAscii = false;
    else
        return;

    QString text = ui->textEditSend->toPlainText();
    if (text.isEmpty())
        return;
    int length = text.length()*3+1;
    char *toText = new char[length];
    memset(toText,'\0',length);
    DecToHexDis(text.toStdString().c_str(), toText, length);

    ui->textEditSend->clear();
    ui->textEditSend->append(QString(toText));
    if (toText != NULL)
    {
        delete toText;
        toText = NULL;
    }
}

